/* eslint-disable no-use-before-define */
/* eslint-disable @typescript-eslint/no-explicit-any */
import { useEffect } from 'preact/hooks';
import { useSignal } from '@preact/signals';
import { IChatToolCall } from '../../interface';
import { createUUID, Namespace } from '../../utils';
import './chat-tool-call-item.scss';

export interface ChatToolCallItemProps {
  /**
   * @description 工具调用
   * @type {IChatToolCall}
   * @memberof ChatToolCallItemProps
   */
  item: IChatToolCall;
}

export const ChatToolCallItem = (props: ChatToolCallItemProps) => {
  const ns = new Namespace('chat-tool-call-item');
  // 是否展开
  const isExpand = useSignal<boolean>(false);
  // 是否正在拷贝
  const isCopying = useSignal<boolean>(false);
  // 定时器ID
  let timerId: NodeJS.Timeout | undefined;

  const uuid = createUUID();

  // 处理折叠
  const onCollapse = () => {
    isExpand.value = !isExpand.value;
    renderJSON(`code-block-${uuid}`, props.item);
  };

  // 处理复制
  const onCopy = (event: MouseEvent) => {
    event.stopPropagation();
    if (timerId) {
      clearTimeout(timerId);
    }
    isCopying.value = true;
    navigator.clipboard.writeText(JSON.stringify(props.item, undefined, 2));
    (window as any).ibiz.message.success('已复制');
    timerId = setTimeout(() => {
      isCopying.value = false;
    }, 2000);
  };

  // 添加 useEffect 来处理组件销毁时的清理，空依赖数组表示只在组件挂载和销毁时执行
  useEffect(() => {
    // 返回清理函数，在组件销毁时执行
    return () => {
      if (timerId) {
        clearTimeout(timerId);
      }
    };
  }, []);

  // 格式化并显示JSON数据
  const renderJSON = (
    elementId: string,
    data: unknown,
    indentLevel: number = 0,
  ): void => {
    const container = document.getElementById(elementId);
    if (!container) return;
    container.innerHTML = '';
    if (!isExpand.value) return;
    const lines = formatJSON(data, indentLevel);
    lines.forEach((line, index) => {
      const lineElement = document.createElement('div');
      lineElement.className = 'code-line';

      const lineNumber = document.createElement('span');
      if (lineNumber) {
        lineNumber.className = 'line-number';
        lineNumber.textContent = (index + 1).toString();
        lineElement.appendChild(lineNumber);
        lineElement.innerHTML += line;
        container.appendChild(lineElement);
      }
    });
  };

  // 递归格式化JSON数据
  const formatJSON = (data: unknown, indentLevel: number = 0) => {
    const indent = '  '.repeat(indentLevel);
    const lines = [];

    if (Array.isArray(data)) {
      if (data.length === 0) {
        return [`${indent}<span class="array">[]</span>`];
      }

      lines.push(`${indent}<span class="array">[</span>`);

      data.forEach((item, index) => {
        const itemLines = formatJSON(item, indentLevel + 1);
        const comma = index < data.length - 1 ? ',' : '';

        if (typeof item === 'object' && item !== null) {
          lines.push(...itemLines.slice(0, -1));
          lines.push(`${itemLines[itemLines.length - 1]}${comma}`);
        } else {
          lines.push(`${itemLines[0]}${comma}`);
        }
      });

      lines.push(`${indent}<span class="array">]</span>`);
    } else if (typeof data === 'object' && data !== null) {
      const keys = Object.keys(data);
      if (keys.length === 0) {
        return [`${indent}<span class="property">{}</span>`];
      }

      lines.push(`${indent}<span class="property">{</span>`);

      keys.forEach((key, index) => {
        const value = (data as Record<string, any>)[key];
        const comma = index < keys.length - 1 ? ',' : '';
        const keyElement = `<span class="json-key">"${key}":</span>`;

        if (typeof value === 'object' && value !== null) {
          const valueLines = formatJSON(value, indentLevel + 1);
          lines.push(`${indent}  ${keyElement} ${valueLines[0].trim()}`);

          if (valueLines.length > 1) {
            lines.push(...valueLines.slice(1, -1));
            lines.push(`${valueLines[valueLines.length - 1]}${comma}`);
          }
        } else {
          const valueElement = formatValue(value);
          lines.push(`${indent}  ${keyElement} ${valueElement}${comma}`);
        }
      });

      lines.push(`${indent}<span class="property">}</span>`);
    } else {
      lines.push(`${indent}${formatValue(data)}`);
    }

    return lines;
  };

  // 格式化基本类型的值
  const formatValue = (value: unknown): string => {
    if (typeof value === 'string') {
      // 检查是否是错误消息
      if (
        value.includes('Failed') ||
        value.includes('Error') ||
        value.includes('ERR_')
      ) {
        return `<span class="error">"${value}"</span>`;
      }
      return `<span class="string">"${value}"</span>`;
    }
    if (typeof value === 'number') {
      return `<span class="number">${value}</span>`;
    }
    if (typeof value === 'boolean') {
      return `<span class="boolean">${value}</span>`;
    }
    if (value === null) {
      return `<span class="null">null</span>`;
    }
    return '';
  };

  return (
    <div className={`${ns.b()}`}>
      <div className={ns.e('header')} onClick={() => onCollapse()}>
        <div className={ns.e('header-left')}>
          <div className={ns.em('header-left', 'caption')}>
            {props.item.name}
          </div>
          <div className={ns.em('header-left', 'desc')}>
            {props.item.parameters.desc}
          </div>
        </div>
        <div className={ns.e('header-right')}>
          {props.item.error && <span style='color: red;'>发生错误</span>}
          {props.item.error && (
            <svg
              xmlns='http://www.w3.org/2000/svg'
              width='13'
              height='13'
              viewBox='0 0 24 24'
              fill='none'
              stroke='red'
              strokeWidth='2'
              strokeLinecap='round'
              strokeLinejoin='round'
              aria-hidden='true'
              style='margin-left: 6px;'
            >
              <path d='m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3'></path>
              <path d='M12 9v4'></path>
              <path d='M12 17h.01'></path>
            </svg>
          )}
          <span className={ns.e('copy')} title='复制'>
            {isCopying.value ? (
              <svg
                xmlns='http://www.w3.org/2000/svg'
                width='14'
                height='14'
                viewBox='0 0 24 24'
                fill='none'
                stroke='rgb(0, 185, 107)'
                strokeWidth='2'
                strokeLinecap='round'
                strokeLinejoin='round'
                className='lucide lucide-check'
                aria-hidden='true'
                style='margin-left: 6px;'
                onClick={(event: MouseEvent) => event.stopPropagation()}
              >
                <path d='M20 6 9 17l-5-5'></path>
              </svg>
            ) : (
              <svg
                xmlns='http://www.w3.org/2000/svg'
                width='14'
                height='14'
                viewBox='0 0 24 24'
                fill='none'
                stroke='currentColor'
                strokeWidth='2'
                strokeLinecap='round'
                strokeLinejoin='round'
                aria-hidden='true'
                style='margin-left: 6px;'
                onClick={(event: MouseEvent) => onCopy(event)}
              >
                <rect width='14' height='14' x='8' y='8' rx='2' ry='2'></rect>
                <path d='M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2'></path>
              </svg>
            )}
          </span>
          <svg
            xmlns='http://www.w3.org/2000/svg'
            width='18'
            height='18'
            viewBox='0 0 24 24'
            fill='none'
            stroke='currentColor'
            strokeWidth='1.5'
            strokeLinecap='round'
            strokeLinejoin='round'
            aria-hidden='true'
            style={{
              'margin-left': ' 6px',
              transform: isExpand.value ? 'rotate(90deg)' : 'rotate(0deg)',
            }}
          >
            <path d='m9 18 6-6-6-6'></path>
          </svg>
        </div>
      </div>
      <div className={ns.e('content')} id={`code-block-${uuid}`}></div>
    </div>
  );
};
